package borderPatrol.Data;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Stack;

import borderPatrol.misc.History;

public class SimulationBoard extends Board {

	public SimulationBoard(int width, int height) {
		super(width, height);
	}

	public SimulationBoard(int width, int height, Stack<int[][]> history, int[] poacherPosition, int[] patrollerPosition, int round, String id, String poacherId, String patrollerId, LinkedList<History> possiblePoacherHistories, LinkedList<History> possiblePatrollerHistories) {
		super(width, height, history, poacherPosition, patrollerPosition, round, id, poacherId, patrollerId, possiblePoacherHistories, possiblePatrollerHistories);
		history.push(new int[][]{poacherPosition, patrollerPosition});
	}

	public String getPoacherId() {
		return poacherId;
	}

	public String getPatrollerId() {
		return patrollerId;
	}

	public String getIdForPlayer(int sign) {
		return sign == 1 ? poacherId : patrollerId;
	}

	public int[] getPositionForPlayer(int sign) {
		return sign == 1 ? poacherPosition : patrollerPosition;
	}

	public void makeSingleMove(Move move, int sign) {

		round++;
		updatePossibleHistories(move, sign);
		addToHistory(move, sign);

		if (sign == 1) {

			poacherPosition[0] = move.x;
			poacherPosition[1] = move.y;

			poacherId = addMoveToId(poacherId, move);

			generatePoacherActions();
			return;
		}

		patrollerPosition[0] = move.x;
		patrollerPosition[1] = move.y;

		patrollerId = addMoveToId(patrollerId, move);

		generatePatrollerActions();
	}

	

	private void addToHistory(Move move, int sign) {
		
		int[][] entry = new int[2][2];
		
		entry[sign - 1][0] =  move.x;
		entry[sign - 1][1] =  move.y;
		
		history.push(entry);
		
	}

	private void updatePossibleHistories(Move move, int sign) {
		
		LinkedList<History> newPossibleHistories = new LinkedList<History>();

		if (history.size() == 0) {
			initiatePossibleHistory(sign, newPossibleHistories);
			return;
		}

		Iterator<History> iterator = getPossibleHistoriesForPlayer(3 - sign).iterator();

		int[][] currentPositions = new int[][]{{-2, -3},{-4, -5}};
		int[][] lastPositions = new int[][]{{-6, -7},{-8, -9}};

		currentPositions[sign - 1] = this.history.peek()[sign - 1];
		if (history.size() >= 2)
			lastPositions[sign - 1] = this.history.get(this.history.size() - 2)[sign - 1];

		while (iterator.hasNext()) {

			History possibleHistory = iterator.next();
			LinkedList<Move> movesForHistory = possibleHistory.possibleMoves;

			currentPositions[2 - sign] = possibleHistory.sequence.peek();
			if (history.size() >= 2) {
				lastPositions[2 - sign] = possibleHistory.sequence.get(possibleHistory.sequence.size() - 2);
			}

			if (isTerminal(currentPositions[0], currentPositions[1], lastPositions[0], lastPositions[1]) != 0) {
				continue;
			}

			for (Move possibleMove : movesForHistory) {
				possibleHistory.sequence.push(new int[] { possibleMove.x, possibleMove.y });
				newPossibleHistories.add(new History(possibleHistory.sequence, generateActionsForPlayerAndPosition(possibleHistory.sequence.peek(), 3 - sign), 3 - sign));
				possibleHistory.sequence.pop();
			}
		}

		setPossibleHistoriesForPlayer(newPossibleHistories, 3 - sign);
	}

	private void initiatePossibleHistory(int sign, LinkedList<History> newPossibleHistories) {
		for (int i = 0; i < 3; i++) {

			Stack<int[]> sequence = new Stack<int[]>();

			sequence.push(new int[] { sign == 1 ? WIDTH - 1 : 0, i });
			newPossibleHistories.add(new History(sequence, generateActionsForPlayerAndPosition(sequence.peek(), 3 - sign), 3 - sign));
		}

		setPossibleHistoriesForPlayer(newPossibleHistories, 3 - sign);
	}

	public int isTerminal(Stack<int[]> history, int sign) {

		if (this.history.size() < 2) {
			return 0;
		}
		
		int[][] positions = new int[2][2];
		int[][] lastPositions = new int[2][2];
		
		positions[sign - 1] = this.history.peek()[sign - 1];
		positions[2 - sign] = history.peek();
		lastPositions[sign - 1] = this.history.get(this.history.size() - 2)[sign - 1];
		lastPositions[2 - sign] = history.get(history.size() - 2);

		return isTerminal(positions[0], positions[1], lastPositions[0], lastPositions[1]);
	}

	public void reverseToPosition(int[] position, LinkedList<History> possibleHistories, int sign) {

		round--;
		setPossibleHistoriesForPlayer(possibleHistories, 3 - sign);
		history.pop();

		if (sign == 1) {
			poacherPosition = position.clone();
			poacherId = poacherId.substring(0, poacherId.length() - 3);
			generatePoacherActions();
			return;
		}

		patrollerPosition = position.clone();
		patrollerId = patrollerId.substring(0, patrollerId.length() - 3);
		generatePatrollerActions();

	}

	public void setOpponentPosition(int[] position, int sign) {
		if (sign == 1) {
			patrollerPosition = position.clone();
			generatePatrollerActions();
		} else {
			poacherPosition = position.clone();
			generatePoacherActions();
		}
	}

	public void resetOpponentPosition(int sign) {
		if (sign == 1) {
			patrollerPosition[0] = -1;
			patrollerPosition[1] = -1;
		} else {
			poacherPosition[0] = -1;
			poacherPosition[1] = -1;
		}
	}
}
